# -*- coding: utf-8 -*-
"""
Wargame AI的“上层AI” —— 用于比赛的第3阶段想定2010431153和2010441253
2020-07
"""

__authur__ = 'Yu XH'

import numpy as np
import copy
from myAI.hexmap.handle_map import *
import time

class RedOprs:
    Tank, IFV, Infantry, UCV, CM_0, CM_1 = 0, 100, 200, 400, 700, 701
    # 初始位置2010431153：Tank: 2526, IFV: 2425, Infantry: 2425, UCV: 2425, CM_0: 2425, CM_1: 2425
    # 初始位置2010441253：Tank: 4244, IFV: 4444, Infantry: 4444, UCV: 4444, CM_0: 4444, CM_1: 4444


class BlueOprs:
    Tank_0, Tank_1, IFV_0, IFV_1, Infantry_0, Infantry_1 = 10000, 10001, 10100, 10101, 10200, 10201
    # 初始位置2010431153：Tank_0: 3849, Tank_1: 4049, IFV_0: 3851, IFV_1: 4052, Infantry_0: 3851, Infantry_1: 4052
    # 初始位置2010441253：Tank_0: 3128, Tank_1: 3229, IFV_0: 3329, IFV_1: 3429, Infantry_0: 3329, Infantry_1: 3429


class FactionAI:
    def __init__(self, myAgent):
        self.color = myAgent.color
        self.scenario = myAgent.scenario
        self.max_step = 1800
        self.task = {}  # 公共变量，保存算子分配的任务信息{obj_id:['outputfire',param1,param2]}
        self.tactic = ['Initiate']  # 我方策略，['Initiate']
        self.group_info = {}  # 保存算子分组信息 {group_name: {group_task: ['ToOccupy', city], obj_ids: [opr1, opr2]}}
        self.task_copy = {}  # factionAI运行中的操作对象，作用是减少对self.task的操作
        self.task_backup = {}  # 用于临时备份某些任务，方便调度
        self.init_deploy_flag = True  # 开局部署兵力的标志
        self.last_observation = myAgent.scenario_info[-1]  # 保存上一步状态，便于和当前状态比较

    def reset(self):
        self.color = None
        self.scenario = None
        self.max_step = 1800
        self.task = {}
        self.tactic = None
        self.group_info = None
        self.task_copy = {}  # factionAI运行中的操作对象，作用是减少对self.task的操作
        self.task_backup = {}  # 用于临时备份某些任务，方便调度
        self.last_observation = None  # 保存上一步状态，便于和当前状态比较

    def update(self, myAgent):
        try:
            while myAgent.thread_factionAI is not None:
                ############# 测试错误 ##########
                # time.sleep(0.5)
                # raise Exception('error')
                #################################

                if myAgent.observation['time']['cur_step'] <= self.last_observation['time']['cur_step']:
                    time.sleep(0.05)
                    continue
                # 读取任务
                self.task_copy = copy.deepcopy(self.task)

                # 如果我方有算子死亡，则将其任务删除
                our_oprs = myAgent.situations.our_oprs
                our_oprs_id = [opr['obj_id'] for opr in our_oprs]
                need_pop = [opr_id for opr_id in self.task_copy.keys() if opr_id not in our_oprs_id]
                for pop_id in need_pop:
                    self.task_copy.pop(pop_id)
                # 如果我方算子有无效任务（Success, Failure, Error等），将任务删除
                our_oprs = myAgent.situations.our_oprs
                for opr in our_oprs:
                    opr_id = opr['obj_id']
                    if opr_id in self.task_copy.keys():
                        if self.task_copy[opr_id][0] in ['Success', 'Failure', 'Error']:
                            self.task_copy.pop(opr_id)

                if not our_oprs:
                    self.task_copy = {}
                elif self.scenario == 2010431153:  # 想定I
                    if self.color == 0:  # 红方策略
                        self.develop_red_strategies_i(myAgent)
                    else:  # 蓝方策略
                        self.develop_blue_strategies_i(myAgent)
                elif self.scenario == 2010441253:  # 想定II
                    if self.color == 0:  # 红方策略
                        self.develop_red_strategies_ii(myAgent)
                    else:  # 蓝方策略
                        self.develop_blue_strategies_ii(myAgent)

                # 写入任务
                self.task = copy.deepcopy(self.task_copy)

                # 更新上一次态势信息
                self.last_observation = myAgent.observation

            print(f'game over: thread_factionAI exit')

        # 如果factionAI执行出错，捕获异常，线程变量置空
        except Exception as e:
            print(f'thread_factionAI failure:')
            myAgent.thread_factionAI = None
        else:
            pass

    # region red_i 2020-7-16
    # def develop_red_strategies_i(self, myAgent):
    #     map_size = myAgent.get_map_size()
    #     cur_step = myAgent.observation['time']['cur_step']
    #     tank, ucv, ifv = myAgent.get_bop(RedOprs.Tank), myAgent.get_bop(RedOprs.UCV), myAgent.get_bop(RedOprs.IFV)
    #     inf, cm_0, cm_1 = myAgent.get_bop(RedOprs.Infantry), myAgent.get_bop(RedOprs.CM_0), myAgent.get_bop(
    #         RedOprs.CM_1)
    #     main_city, secondary_city = myAgent.get_city(3636), myAgent.get_city(4039)
    #
    #     # === 确定self.tactic ===
    #     # -- 强行夺控，步兵死亡 --
    #     if not inf:
    #         vehicle_count, tank_count = 0, 0
    #         for enemy_info in myAgent.situations.enemies:
    #             enemy = enemy_info['operator']
    #             if not enemy_info['spread_flag']:  # 避免死亡算子计算错误
    #                 continue
    #             if enemy['type'] == BopType.Vehicle:
    #                 vehicle_count += 1
    #                 if enemy['sub_type'] == BopType.Tank:
    #                     tank_count += 1
    #         if tank and (ucv or ifv):  # 我方至少有包含坦克的2个以上车辆算子
    #             if vehicle_count == 2 and tank_count <= 1:  # 不能敌方剩余2个坦克
    #                 self.tactic = ['ForceControl']  # 强行夺控
    #     if self.max_step - cur_step <= 100 and main_city['flag'] != self.color:
    #         self.tactic = ['ForceControl']  # 强行夺控
    #     # -- 扩大战果 --
    #     enemy_count, enemies_left = 0, []
    #     for enemy_info in myAgent.situations.enemies:
    #         if np.max(enemy_info['pos_probs']) < 0.1:  # 避免死亡算子计算错误
    #             continue
    #         enemy_count += 1
    #         enemies_left.append(enemy_info['operator'])
    #     if enemy_count == 0:
    #         if tank or ucv or ifv or inf:  # 我方有幸存算子
    #             self.tactic = ['ExpandVictory']  # 扩大战果
    #     elif enemy_count <= 1:
    #         if tank and ucv and ifv:  # 我方所有车辆算子都在
    #             self.tactic = ['ExpandVictory']  # 扩大战果
    #     # -- 发射第二枚巡飞弹 --
    #     if self.check_red_launch_2nd_cm(myAgent):
    #         self.task_backup[RedOprs.IFV] = self.task_copy.pop(RedOprs.IFV)  # 备份原任务
    #         self.task_copy[RedOprs.IFV] = ['unload', RedOprs.CM_1, False]  # +++
    #         self.task_copy[RedOprs.CM_1] = ['cruise_missile']
    #     if cm_1:
    #         if cm_1['on_board'] == 1 and cm_1['get_off_remain_time'] > 0 and RedOprs.IFV in self.task_backup.keys():
    #             self.task_copy[RedOprs.IFV] = self.task_backup.pop(RedOprs.IFV)
    #
    #     # === 任务分派 ===
    #     if 'Initiate' in self.tactic:  # 初始部署
    #         self.task_copy[RedOprs.IFV] = ['ambush2nd', 2930, False]  # +++
    #         self.task_copy[RedOprs.UCV] = ['ambush2nd', 2229, True]  # +++
    #         self.task_copy[RedOprs.Tank] = ['ambush2nd', 2433, False]  # +++
    #         self.task_copy[RedOprs.Infantry] = ['maneuver', 2726]  # +++
    #         self.tactic = ['Deploy2nd']  # 第2次部署
    #     elif 'Deploy2nd' in self.tactic:  # 第2次部署
    #         # --- 为Tank分派任务 ---
    #         if tank:
    #             if cur_step >= 280 and tank['cur_hex'] == 2433 and tank['stop'] == 1:
    #                 self.task_copy[RedOprs.Tank] = ['ambush3rd', 2337, False]  # +++
    #         # --- 为UCV分派任务
    #         if ucv:
    #             if cur_step >= 280 and ucv['cur_hex'] == 2229 and ucv['stop'] == 1:
    #                 self.task_copy[RedOprs.UCV] = ['ambush3rd', 2638, True]  # +++
    #         # --- 为IFV分派任务 ---
    #         if ifv:
    #             if cur_step >= 280 and ifv['cur_hex'] == 2930 and ifv['stop'] == 1:
    #                 self.task_copy[RedOprs.IFV] = ['maneuver', 2726]  # +++
    #             if ifv['cur_hex'] == 2726:
    #                 if cm_0['get_off_remain_time'] <= 0 and cm_0['on_board'] == 1:
    #                     self.task_copy[RedOprs.IFV] = ['unload', RedOprs.CM_0, False]  # +++
    #                     self.task_copy[RedOprs.CM_0] = ['cruise_missile']  # +++
    #                 if inf:
    #                     if inf['cur_hex'] == 2726 and (cm_0['get_off_remain_time'] > 0 or cm_0['on_board'] == 0) and \
    #                             inf['on_board'] == 0 and inf['get_on_remain_time'] <= 0:
    #                         self.task_copy[RedOprs.IFV] = ['load', RedOprs.Infantry]  # +++
    #                     if inf['cur_hex'] == 2726 and inf['get_on_remain_time'] > 0:
    #                         # self.task_copy[RedOprs.IFV] = ['rapid_march', 3427, 1]  # +++
    #                         self.task_copy[RedOprs.IFV] = ['rapid_march', 3632, 1]  # +++
    #                         self.tactic = ['Fight']  # 交战阶段
    #                 else:
    #                     if cm_0['get_off_remain_time'] > 0:
    #                         self.task_copy[RedOprs.IFV] = ['ambush2nd', 2930, False]  # +++
    #                         self.tactic = ['Fight']  # 交战阶段
    #     elif 'Fight' in self.tactic:  # 交战阶段
    #         # --- 为Tank分派任务 ---
    #         if tank:
    #             if cur_step >= 790 and tank['cur_hex'] == 2337:
    #                 self.task_copy[RedOprs.Tank] = ['ambush3rd', 3031, False]
    #         # --- 为IFV分派任务 ---
    #         if ifv and inf:
    #             # if ifv['cur_hex'] == 3427:
    #             #     if RedOprs.Infantry in ifv['passenger_ids']:
    #             #         self.task_copy[RedOprs.IFV] = ['rapid_march', 3531, 1]  # +++
    #             # if ifv['cur_hex'] == 3531:
    #             #     if RedOprs.Infantry in ifv['passenger_ids']:
    #             #         self.task_copy[RedOprs.IFV] = ['deliver', RedOprs.Infantry, 3632]  # +++
    #             if ifv['cur_hex'] == 3632 and inf['get_off_remain_time'] <= 0:
    #                 self.task_copy[RedOprs.IFV] = ['deliver', RedOprs.Infantry, 3632]  # +++
    #             if ifv['cur_hex'] == 3632 and inf['get_off_remain_time'] > 0:
    #                 self.task_copy[RedOprs.IFV] = ['ambush3rd', 3631, True]  # +++
    #                 self.task_copy[RedOprs.Infantry] = ['ambush2nd', 3635, False]  # +++
    #         # --- 为步兵分派任务 ---
    #         if inf:
    #             if inf['cur_hex'] == 3635 and main_city['flag'] != self.color and (
    #                     not enemy_around_city(main_city['coord'], myAgent)):
    #                 self.task_copy[RedOprs.Infantry] = ['control', 3636]  # +++
    #             if inf['cur_hex'] == 3636 and myAgent.get_city(3636)['flag'] == self.color:
    #                 self.task_copy[RedOprs.Infantry] = ['ambush2nd', 3635, False]  # +++
    #         # --- 为UCV分派任务
    #         if ucv:
    #             if cur_step >= 1035 and ucv['cur_hex'] == 2638:
    #                 self.task_copy[RedOprs.UCV] = ['ambush3rd', 2838, False]  # +++
    #         # --- 为巡飞弹分派任务 ---
    #         if self.check_red_cm_shoot(myAgent):
    #             cm = cm_0 if cm_0 else cm_1
    #             if cm['obj_id'] in self.task_copy.keys():
    #                 if 'targeted_kill' not in self.task_copy[cm['obj_id']]:
    #                     tar_id = None
    #                     for inf_id_b in [BlueOprs.Infantry_0, BlueOprs.Infantry_1]:
    #                         inf_b = myAgent.get_enemy(inf_id_b)
    #                         if inf_b:
    #                             if inf_b['cur_hex'] == 3636:
    #                                 tar_id = inf_id_b
    #                     if tar_id:
    #                         self.task_copy[cm['obj_id']] = ['targeted_kill', tar_id]
    #     elif 'ForceControl' in self.tactic:  # 强行夺控
    #         use_oprs = []
    #         if tank:
    #             use_oprs.append(tank)
    #         if ifv:
    #             use_oprs.append(ifv)
    #         if ucv:
    #             use_oprs.append(ucv)
    #         # - 选出夺控的算子 -
    #         cost_matrix = myAgent.my_map['cost_matrix'][0]
    #         control_opr = None
    #         if inf:
    #             if inf['keep'] == 0:
    #                 control_opr = inf
    #         elif not control_opr:
    #             min_dist = 1000
    #             for opr in use_oprs:
    #                 cur_dist = cost_matrix[mapid_2_matind(3636, map_size), mapid_2_matind(opr['cur_hex'], map_size)]
    #                 if cur_dist < min_dist:
    #                     min_dist = cur_dist
    #                     control_opr = opr
    #             use_oprs.remove(control_opr)  # 确定进攻算子
    #         # - 分派任务 -
    #         main_city = myAgent.get_city(3636)
    #         if main_city['flag'] == self.color:
    #             self.task_copy[control_opr['obj_id']] = ['defend_firepower', 3636, []]  # +++ 反夺控
    #         else:
    #             self.task_copy[control_opr['obj_id']] = ['control', 3636]  # +++ 夺控
    #         if use_oprs:
    #             # 确定进攻区域和敌人所在方向
    #             tar_area, enemy_directions = [], []
    #             for enemy_info in myAgent.situations.enemies:
    #                 enemy_loc = enemy_info['operator']['cur_hex']
    #                 if cal_distance(enemy_loc, 3636) <= 5:  # 5格以内
    #                     tar_area.append(enemy_loc)
    #                 enemy_directions.append(get_direction(3636, enemy_loc))
    #             enemy_directions = list(set(enemy_directions))
    #             for opr in use_oprs:
    #                 if tar_area:
    #                     self.task_copy[opr['obj_id']] = ['output_firepower', tar_area]  # +++
    #                 else:
    #                     self.task_copy[opr['obj_id']] = ['defend_firepower', 3636, enemy_directions]  # +++
    #     elif 'ExpandVictory' in self.tactic:  # 扩大战果
    #         use_oprs = []
    #         if tank:
    #             use_oprs.append(tank)
    #         if ifv:
    #             use_oprs.append(ifv)
    #         if ucv:
    #             use_oprs.append(ucv)
    #         if inf:
    #             use_oprs.append(inf)
    #         cost_matrix = myAgent.my_map['cost_matrix'][0]
    #         if enemy_count == 0:  # 没有敌人，直接夺控
    #             if main_city['flag'] != self.color:
    #                 min_dist_main, control_opr_main = 1000, None
    #                 for opr in use_oprs:
    #                     if opr['type'] == BopType.Vehicle:
    #                         cur_dist = cost_matrix[
    #                             mapid_2_matind(main_city['coord'], map_size), mapid_2_matind(opr['cur_hex'], map_size)]
    #                     else:
    #                         cur_dist = cal_distance(main_city['coord'], opr['cur_hex']) * 144
    #                     if cur_dist < min_dist_main:
    #                         min_dist_main = cur_dist
    #                         control_opr_main = opr
    #                 use_oprs.remove(control_opr_main)  # 确定主夺控点的夺控算子
    #                 self.task_copy[control_opr_main['obj_id']] = ['control', main_city['coord']]  # +++
    #             if secondary_city['flag'] != self.color:
    #                 min_dist_secondary, control_opr_secondary = 1000, None
    #                 for opr in use_oprs:
    #                     if opr['type'] == BopType.Vehicle:
    #                         cur_dist = cost_matrix[
    #                             mapid_2_matind(secondary_city['coord'], map_size), mapid_2_matind(opr['cur_hex'],
    #                                                                                               map_size)]
    #                     else:
    #                         cur_dist = cal_distance(secondary_city['coord'], opr['cur_hex']) * 144
    #                     if cur_dist < min_dist_secondary:
    #                         min_dist_secondary = cur_dist
    #                         control_opr_secondary = opr
    #                 use_oprs.remove(control_opr_secondary)  # 确定主夺控点的夺控算子
    #                 self.task_copy[control_opr_secondary['obj_id']] = ['control', secondary_city['coord']]  # +++
    #         else:  # 还有一个敌人
    #             if main_city['flag'] != self.color:
    #                 if cal_distance(main_city['coord'], enemies_left[0]['cur_hex']) > 3:
    #                     min_dist_main, control_opr_main = 1000, None
    #                     for opr in use_oprs:
    #                         if opr['type'] == BopType.Vehicle:
    #                             cur_dist = cost_matrix[
    #                                 mapid_2_matind(main_city['coord'], map_size), mapid_2_matind(opr['cur_hex'],
    #                                                                                              map_size)]
    #                         else:
    #                             cur_dist = cal_distance(main_city['coord'], opr['cur_hex']) * 144
    #                         if cur_dist < min_dist_main:
    #                             min_dist_main = cur_dist
    #                             control_opr_main = opr
    #                     use_oprs.remove(control_opr_main)  # 确定主夺控点的夺控算子
    #                     self.task_copy[control_opr_main['obj_id']] = ['control', main_city['coord']]  # +++
    #             if secondary_city['flag'] != self.color:
    #                 if cal_distance(main_city['coord'], enemies_left[0]['cur_hex']) > 3:
    #                     min_dist_secondary, control_opr_secondary = 1000, None
    #                     for opr in use_oprs:
    #                         if opr['type'] == BopType.Vehicle:
    #                             cur_dist = cost_matrix[
    #                                 mapid_2_matind(secondary_city['coord'], map_size), mapid_2_matind(opr['cur_hex'],
    #                                                                                                   map_size)]
    #                         else:
    #                             cur_dist = cal_distance(secondary_city['coord'], opr['cur_hex']) * 144
    #                         if cur_dist < min_dist_secondary:
    #                             min_dist_secondary = cur_dist
    #                             control_opr_secondary = opr
    #                     use_oprs.remove(control_opr_secondary)  # 确定主夺控点的夺控算子
    #                     self.task_copy[control_opr_secondary['obj_id']] = ['control', secondary_city['coord']]  # +++
    #             for opr in use_oprs:
    #                 self.task_copy[opr['obj_id']] = ['output_firepower', enemies_left[0]['cur_hex']]  # +++
    # endregion

    def develop_red_strategies_i(self, myAgent):
        map_size = myAgent.get_map_size()
        cur_step = myAgent.observation['time']['cur_step']
        tank, ucv, ifv = myAgent.get_bop(RedOprs.Tank), myAgent.get_bop(RedOprs.UCV), myAgent.get_bop(RedOprs.IFV)
        inf, cm_0, cm_1 = myAgent.get_bop(RedOprs.Infantry), myAgent.get_bop(RedOprs.CM_0), myAgent.get_bop(
            RedOprs.CM_1)
        main_city, secondary_city = myAgent.get_city(3636), myAgent.get_city(4039)

        ''' === 确定self.tactic === '''
        # == 夺控阶段 ==
        if tank:
            flag_blue_tank = False
            for enemy_info in myAgent.situations.enemies:
                if enemy_info['spread_flag']:
                    enemy = enemy_info['operator']
                    if enemy['sub_type'] == BopType.Tank:
                        flag_blue_tank = True
                        break
            if not flag_blue_tank and cur_step >= 900:
                self.tactic = ['Control']  # 强行夺控

        ''' === 任务分派 === '''
        if 'Initiate' in self.tactic:
            if tank:
                if tank['cur_hex'] == 2526:
                    self.task_copy[RedOprs.Tank] = ['ambush', 2433]
                if cur_step >= 280 and tank['cur_hex'] == 2433:
                    self.task_copy[RedOprs.Tank] = ['ambush', 2830]
            if ifv:
                if ifv['cur_hex'] == 2425:
                    self.task_copy[RedOprs.IFV] = ['ambush2nd', 2930, False]
                if cm_0:
                    if cur_step >= 280 and cm_0['get_off_remain_time'] <= 0 and cm_0['on_board'] == 1:
                        self.task_copy[RedOprs.IFV] = ['unload', RedOprs.CM_0, False]  # +++
                        self.task_copy[RedOprs.CM_0] = ['cruise_missile']  # +++
                    if cm_0['get_off_remain_time'] > 0:
                        self.task_copy[RedOprs.IFV] = ['rapid_march', 2729, 1]  # +++
                if ifv['cur_hex'] == 2729:
                    self.task_copy[RedOprs.IFV] = ['ambush2nd', 2729, False]
            if ucv:
                if ucv['cur_hex'] == 2425:
                    self.task_copy[RedOprs.UCV] = ['ambush2nd', 2231, False]
                if cur_step >= 280 and ucv['cur_hex'] == 2231:
                    self.task_copy[RedOprs.UCV] = ['ambush3rd', 2231, True]
            if inf:
                if inf['cur_hex'] == 2425:
                    self.task_copy[RedOprs.Infantry] = ['ambush3rd', 2630, True]
        if 'Control' in self.tactic:
            # use_oprs = []
            # for opr in [ifv, ucv]:
            #     if opr:
            #         use_oprs.append(opr)
            remain_enemies = myAgent.situations.enemies
            vehicle_area, infantry_area = [], []
            if remain_enemies:
                for enemy_info in remain_enemies:
                    enemy = enemy_info['operator']
                    if cal_distance(enemy['cur_hex'], main_city['coord']) <= 3:
                        if enemy['type'] == BopType.Vehicle:
                            vehicle_area.append(enemy['cur_hex'])
                        elif enemy['type'] == BopType.Infantry:
                            infantry_area.append(enemy['cur_hex'])
            if vehicle_area:
                # for opr in use_oprs:
                #     self.task_copy[opr['obj_id']] = ['output_firepower', vehicle_area]  # +++
                if tank:
                    self.task_copy[RedOprs.Tank] = ['fire_propulsion']
            elif infantry_area:
                # for opr in use_oprs:
                #     self.task_copy[opr['obj_id']] = ['output_firepower', infantry_area]  # +++
                if tank:
                    tar_city = None
                    for city in [main_city, secondary_city]:
                        if city['flag'] != self.color:
                            flag_anticontrol = False
                            for loc in infantry_area:
                                if cal_distance(loc, city['cood']) <= 1:
                                    flag_anticontrol = True
                                    break
                            if not flag_anticontrol:
                                tar_city = city
                    if tar_city:
                        self.task_copy[RedOprs.Tank] = ['control', tar_city['coord']]
                    else:
                        self.task_copy[RedOprs.Tank] = ['ambush', main_city['coord']]
            cm = cm_0 if cm_0 else (cm_1 if cm_1 else None)
            if cm:
                tar_opr = min(remain_enemies, key=lambda x: cal_distance(x['operator']['cur_hex'], main_city['coord']))
                if tank:
                    if tank['cur_hex'] == main_city['coord']:
                        self.task_copy[cm['obj_id']] = ['targeted_kill', tar_opr['obj_id']]
        # == 发射第2枚巡飞弹 ==
        if self.check_red_launch_2nd_cm(myAgent) and cur_step >= 600:
            if RedOprs.IFV in self.task_copy.keys():
                if 'unload' not in self.task_copy[RedOprs.IFV]:
                    self.task_backup[RedOprs.IFV] = self.task_copy.pop(RedOprs.IFV)  # 备份原任务
                    self.task_copy[RedOprs.IFV] = ['unload', RedOprs.CM_1, False]  # +++
                    self.task_copy[RedOprs.CM_1] = ['cruise_missile']
            else:
                self.task_copy[RedOprs.IFV] = ['unload', RedOprs.CM_1, False]  # +++
                self.task_copy[RedOprs.CM_1] = ['cruise_missile']
        if cm_1:
            if cm_1['on_board'] == 1 and cm_1['get_off_remain_time'] > 0 and RedOprs.IFV in self.task_backup.keys():
                self.task_copy[RedOprs.IFV] = self.task_backup.pop(RedOprs.IFV)
        # == 巡飞弹的条件打击任务 ==
        cm_0, cm_1 = myAgent.get_bop(RedOprs.CM_0), myAgent.get_bop(RedOprs.CM_1)
        cm = cm_0 if cm_0 else (cm_1 if cm_1 else None)
        if cm:
            flag_ifv_getoff = False
            cm_target = None
            enemy_ifv_0, enemy_ifv_1 = myAgent.get_enemy(BlueOprs.IFV_0), myAgent.get_enemy(BlueOprs.IFV_1)
            if enemy_ifv_0:
                if enemy_ifv_0['get_off_partner_id']:
                    flag_ifv_getoff = True
                    cm_target = BlueOprs.IFV_0
            if not flag_ifv_getoff:
                if enemy_ifv_1:
                    if enemy_ifv_1['get_off_partner_id']:
                        flag_ifv_getoff = True
                        cm_target = BlueOprs.IFV_1
            if flag_ifv_getoff:
                self.task_copy[cm['obj_id']] = ['targeted_kill', cm_target]

    def develop_blue_strategies_i(self, myAgent):
        map_size = myAgent.get_map_size()
        cur_step = myAgent.observation['time']['cur_step']
        tank_0, tank_1 = myAgent.get_bop(BlueOprs.Tank_0), myAgent.get_bop(BlueOprs.Tank_1)
        ifv_0, ifv_1 = myAgent.get_bop(BlueOprs.IFV_0), myAgent.get_bop(BlueOprs.IFV_1)
        inf_0, inf_1 = myAgent.get_bop(BlueOprs.Infantry_0), myAgent.get_bop(BlueOprs.Infantry_1)
        main_city, secondary_city = myAgent.get_city(3636), myAgent.get_city(4039)

        ''' === 确定self.tactic === '''
        # -- 夺控阶段 --
        if main_city['flag'] != self.color or secondary_city['flag'] != self.color:
            for opr in myAgent.get_our_oprs():
                if opr['type'] == BopType.Vehicle:
                    if self.max_step - cur_step <= 200:
                        self.tactic = ['Control']

        ''' === 任务分派 === '''
        if 'Initiate' in self.tactic:  # 初始部署
            flag_red_tank = False
            red_tank_info = myAgent.get_enemy_info(RedOprs.Tank)
            if red_tank_info:
                if red_tank_info['spread_flag']:
                    if cal_distance(red_tank_info['operator']['cur_hex'], 3838) <= 3:
                        flag_red_tank = True
            if tank_0:
                if tank_0['cur_hex'] == 3849:
                    self.task_copy[BlueOprs.Tank_0] = ['maneuver', 3940]  # +++
                elif tank_0['cur_hex'] == 3940:
                    self.task_copy[BlueOprs.Tank_0] = ['ambush', 3838]  # +++
                if flag_red_tank:
                    if cal_distance(tank_0['cur_hex'], 3838) <= 1:
                        self.task_copy[BlueOprs.Tank_0] = ['ambush', 3736]  # +++
                else:
                    if cal_distance(tank_0['cur_hex'], 3736) <= 1:
                        self.task_copy[BlueOprs.Tank_0] = ['ambush', 3838]  # +++
            if tank_1:
                if tank_1['cur_hex'] == 4049:
                    self.task_copy[BlueOprs.Tank_1] = ['maneuver', 3940]  # +++
                elif tank_1['cur_hex'] == 3940:
                    self.task_copy[BlueOprs.Tank_1] = ['ambush', 3837]  # +++
                if flag_red_tank:
                    if cal_distance(tank_1['cur_hex'], 3837) <= 1:
                        if tank_0:
                            self.task_copy[BlueOprs.Tank_1] = ['ambush', 3836]  # +++
                        else:
                            self.task_copy[BlueOprs.Tank_1] = ['ambush', 3736]  # +++
                else:
                    if cal_distance(tank_1['cur_hex'], 3736) <= 1 or cal_distance(tank_1['cur_hex'], 3836) <= 1:
                        self.task_copy[BlueOprs.Tank_1] = ['ambush', 3837]  # +++
            if ifv_0:
                if ifv_0['cur_hex'] == 3851:
                    if inf_0['on_board'] == 0 and inf_0['get_on_remain_time'] <= 0:
                        self.task_copy[BlueOprs.IFV_0] = ['load', BlueOprs.Infantry_0]  # +++
                    elif inf_0['get_on_remain_time'] > 0:
                        self.task_copy[BlueOprs.IFV_0] = ['maneuver', 4243]  # +++
                elif ifv_0['cur_hex'] == 4243:
                    self.task_copy[BlueOprs.IFV_0] = ['deliver', BlueOprs.Infantry_0, 4138]  # +++
                if ifv_0['cur_hex'] == 4138 and inf_0['get_off_remain_time'] > 0:
                    self.task_copy[BlueOprs.IFV_0] = ['maneuver', [4038]]
                    self.task_copy[BlueOprs.Infantry_0] = ['maneuver', 4039]  # +++
                if ifv_0['cur_hex'] == 4038:
                    self.task_copy[BlueOprs.IFV_0] = ['ambush2nd', 4038, False]  # +++
            if ifv_1:
                if ifv_1['cur_hex'] == 4052:
                    if inf_1['on_board'] == 0 and inf_1['get_on_remain_time'] <= 0:
                        self.task_copy[BlueOprs.IFV_1] = ['load', BlueOprs.Infantry_1]  # +++
                    elif inf_1['get_on_remain_time'] > 0:
                        self.task_copy[BlueOprs.IFV_1] = ['maneuver', 4143]  # +++
                elif ifv_1['cur_hex'] == 4143:
                    self.task_copy[BlueOprs.IFV_1] = ['maneuver', 3940]  # +++
                elif ifv_1['cur_hex'] == 3940:
                    self.task_copy[BlueOprs.IFV_1] = ['maneuver', [3840, 3839, 3738]]  # +++
                elif ifv_1['cur_hex'] == 3738 and inf_1['on_board'] == 1 and inf_1['get_off_remain_time'] <= 0:
                    self.task_copy[BlueOprs.IFV_1] = ['deliver', BlueOprs.Infantry_1, 3738]  # +++
                if ifv_1['cur_hex'] == 3738 and inf_1['get_off_remain_time'] > 0:
                    self.task_copy[BlueOprs.IFV_1] = ['rapid_march', 3937, 0.2]  # +++
                    self.task_copy[BlueOprs.Infantry_1] = ['ambush2nd', 3736, False]  # +++
                if ifv_1['cur_hex'] == 3937:
                    self.task_copy[BlueOprs.IFV_1] = ['ambush2nd', 3937, False]  # +++
                if not ifv_0:
                    self.task_copy[BlueOprs.IFV_1] = ['ambush2nd', 4038, False]  # +++
            if inf_0:
                if inf_0['cur_hex'] == 4039:
                    self.task_copy[BlueOprs.Infantry_0] = ['ambush2nd', 3639, True]  # +++
            if inf_1:
                if inf_1['cur_hex'] == 3736:
                    if flag_red_tank:
                        if tank_0 or tank_1:
                            self.task_copy[BlueOprs.Infantry_1] = ['ambush2nd', 3636, False]  # +++
                if inf_1['cur_hex'] == 3636:
                    if not flag_red_tank:
                        self.task_copy[BlueOprs.Infantry_1] = ['ambush2nd', 3736, False]  # +++
        if 'Control' in self.tactic:  # 夺控阶段
            use_oprs = []
            for opr in [tank_0, tank_1, ifv_0, ifv_1, inf_0, inf_1]:
                if opr:
                    use_oprs.append(opr)
            # -- 确定夺控算子 --
            control_opr_main, control_opr_secondary = None, None
            if use_oprs:
                min_dist = 1000
                for opr in use_oprs:
                    cost_matrix = myAgent.my_map['cost_matrix'][0]
                    if opr['type'] == BopType.Vehicle:
                        cur_dist = cost_matrix[
                            mapid_2_matind(main_city['coord'], map_size), mapid_2_matind(opr['cur_hex'], map_size)]
                    else:
                        cur_dist = cal_distance(main_city['coord'], opr['cur_hex']) * 144
                    if cur_dist < min_dist:
                        min_dist = cur_dist
                        control_opr_main = opr
                use_oprs.remove(control_opr_main)  # 确定夺控算子
            if use_oprs:
                min_dist = 1000
                for opr in use_oprs:
                    cost_matrix = myAgent.my_map['cost_matrix'][0]
                    if opr['type'] == BopType.Vehicle:
                        cur_dist = cost_matrix[
                            mapid_2_matind(secondary_city['coord'], map_size), mapid_2_matind(opr['cur_hex'], map_size)]
                    else:
                        cur_dist = cal_distance(secondary_city['coord'], opr['cur_hex']) * 144
                    if cur_dist < min_dist:
                        min_dist = cur_dist
                        control_opr_secondary = opr
                use_oprs.remove(control_opr_secondary)  # 确定夺控算子
            # -- 确定目标区域 --
            tar_area = []
            for enemy_info in myAgent.situations.enemies:
                enemy_loc = enemy_info['operator']['cur_hex']
                if cal_distance(enemy_loc, main_city['coord']) <= 3:  # 3格以内
                    tar_area.append(enemy_loc)
                elif cal_distance(enemy_loc, secondary_city['coord']) <= 3:  # 3格以内
                    tar_area.append(enemy_loc)
            if not tar_area:
                tar_area = get_range(main_city['coord'], 3, map_size)
            if control_opr_main:
                if main_city['flag'] != self.color:
                    # -- 分派夺控任务 --
                    self.task_copy[control_opr_main['obj_id']] = ['control', main_city['coord']]  # +++
                else:
                    # -- 分派反夺控任务 --
                    self.task_copy[control_opr_main['obj_id']] = ['defend_firepower', main_city['coord'], []]  # +++
            if control_opr_secondary:
                if secondary_city['flag'] != self.color:
                    # -- 分派夺控任务 --
                    self.task_copy[control_opr_secondary['obj_id']] = ['control', secondary_city['coord']]  # +++
                else:
                    # -- 分派反夺控任务 --
                    self.task_copy[control_opr_secondary['obj_id']] = ['defend_firepower', secondary_city['coord'], []]  # +++
            for opr in use_oprs:
                if opr['sub_type'] != BopType.Tank:
                    self.task_copy[opr['obj_id']] = ['output_firepower', tar_area]  # +++

        ''' === 零星动作 === '''
        # == 主次夺控点的夺控 ==
        if main_city['flag'] != self.color:
            first_control_opr, second_control_opr = None, None
            for opr in myAgent.get_our_oprs():
                if cal_distance(opr['cur_hex'], main_city['coord']) <= 1:
                    if opr['type'] == BopType.Infantry and not first_control_opr:
                        first_control_opr = opr
                    elif opr['sub_type'] == BopType.IFV and not second_control_opr:
                        second_control_opr = opr
            can_control = True
            for enemy_info in myAgent.situations.enemies:
                enemy = enemy_info['operator']
                if cal_distance(enemy['cur_hex'], main_city['coord']) <= 1 and enemy_info['spread_flag']:
                    can_control = False
            if can_control:
                control_opr = first_control_opr if first_control_opr else (second_control_opr if second_control_opr else None)
                if control_opr:
                    self.task_copy[control_opr['obj_id']] = ['control', main_city['coord']]  # +++
        if secondary_city['flag'] != self.color:
            first_control_opr, second_control_opr = None, None
            for opr in myAgent.get_our_oprs():
                if cal_distance(opr['cur_hex'], secondary_city['coord']) <= 1:
                    if opr['type'] == BopType.Infantry and not first_control_opr:
                        first_control_opr = opr
                    elif opr['sub_type'] == BopType.IFV and not second_control_opr:
                        second_control_opr = opr
            can_control = True
            for enemy_info in myAgent.situations.enemies:
                enemy = enemy_info['operator']
                if cal_distance(enemy['cur_hex'], secondary_city['coord']) <= 1 and enemy_info['spread_flag']:
                    can_control = False
            if can_control:
                control_opr = first_control_opr if first_control_opr else (second_control_opr if second_control_opr else None)
                if control_opr:
                    self.task_copy[control_opr['obj_id']] = ['control', secondary_city['coord']]  # +++
        for obj_id, task in self.task_copy.items():
            if 'control' in task:
                if myAgent.get_bop(obj_id)['cur_hex'] == main_city['coord']:
                    self.task_copy[obj_id] = ['ambush2nd', 3736, False]
                if myAgent.get_bop(obj_id)['cur_hex'] == secondary_city['coord']:
                    self.task_copy[obj_id] = ['ambush2nd', 4038, False]
        # == 补位 ==
        flag_in_main_city = False
        for opr in myAgent.get_our_oprs():
            if opr['cur_hex'] in [3736, 3636]:
                flag_in_main_city = True
        if not inf_1 and not flag_in_main_city:
            if inf_0:
                self.task_copy[BlueOprs.Infantry_0] = ['ambush2nd', 3736, False]  # +++
            elif ifv_1:
                self.task_copy[BlueOprs.IFV_1] = ['ambush3rd', 3736, True]  # +++

    def develop_red_strategies_ii(self, myAgent):
        map_size = myAgent.get_map_size()
        cur_step = myAgent.observation['time']['cur_step']
        tank, ucv, ifv = myAgent.get_bop(RedOprs.Tank), myAgent.get_bop(RedOprs.UCV), myAgent.get_bop(RedOprs.IFV)
        inf, cm_0, cm_1 = myAgent.get_bop(RedOprs.Infantry), myAgent.get_bop(RedOprs.CM_0), myAgent.get_bop(
            RedOprs.CM_1)
        blue_tank_0, blue_tank_1 = myAgent.get_enemy(BlueOprs.Tank_0), myAgent.get_enemy(BlueOprs.Tank_1)
        main_city, secondary_city = myAgent.get_city(3636), myAgent.get_city(3739)

        # === 确定self.tactic ===
        # -- 夺控阶段 --
        control_flag = True
        for enemy_info in myAgent.situations.enemies:
            if enemy_info['operator']['sub_type'] == BopType.Tank:
                control_flag = False
        if control_flag and tank:
            self.tactic = ["Control"]

        # === 任务分派 ===
        if 'Initiate' in self.tactic:  # 初始部署
            if tank:
                if tank['cur_hex'] == 4244:
                    self.task_copy[RedOprs.Tank] = ['rapid_march', secondary_city['coord'], 0]  # +++
                if tank['cur_hex'] == secondary_city['coord']:
                    # 判断是否打战车
                    if 260 <= cur_step < 300 and 'ambush' not in self.task_copy[RedOprs.Tank]:
                        flag_ambush = False
                        if blue_tank_0:
                            if blue_tank_0['cur_hex'] in [3436, 3535, 3635, 3636, 3536, 3439]:
                                flag_ambush = True
                        if blue_tank_1 and not flag_ambush:
                            if blue_tank_1['cur_hex'] in [3436, 3535, 3635, 3636, 3536, 3439]:
                                flag_ambush = True
                        if flag_ambush:  # 在3640打伏击
                            self.task_copy[RedOprs.Tank] = ['ambush', 3640]  # +++
                        else:
                            self.task_copy[RedOprs.Tank] = ['ambush', 3636]  # +++
                flag_output_firepower = False
                if RedOprs.Tank in self.task_copy.keys():
                    if 'output_firepower' in self.task_copy[RedOprs.Tank]:
                        flag_output_firepower = True
                if tank['cur_hex'] == 3636 or flag_output_firepower:
                    if not tank['see_enemy_bop_ids']:
                        self.task_copy[RedOprs.Tank] = ['ambush', 3736]  # +++
                    else:
                        blue_tank_in_sight, blue_ifv_locs = False, []
                        for ene_id in tank['see_enemy_bop_ids']:
                            enemy = myAgent.get_bop(ene_id)
                            if enemy:
                                if enemy['sub_type'] == BopType.Tank:
                                    blue_tank_in_sight = True
                                    break
                                elif enemy['sub_type'] == BopType.IFV:
                                    blue_ifv_locs.append(enemy['cur_hex'])
                        if blue_tank_in_sight:
                            self.task_copy[RedOprs.Tank] = ['ambush', 3736]  # +++
                        elif blue_ifv_locs:
                            self.task_copy[RedOprs.Tank] = ['output_firepower', blue_ifv_locs]  # +++
                        else:
                            self.task_copy[RedOprs.Tank] = ['ambush', 3736]  # +++
            if ucv:
                if ucv['cur_hex'] == 4444:
                    self.task_copy[RedOprs.UCV] = ['ambush3rd', 5242, False]
                # UCV的引导射击任务
            if ifv:
                if ifv['cur_hex'] == 4444:
                    if cm_0:
                        if cm_0['get_off_remain_time'] <= 0 and cm_0['on_board'] == 1:
                            self.task_copy[RedOprs.IFV] = ['unload', RedOprs.CM_0, False]  # +++
                            self.task_copy[RedOprs.CM_0] = ['maneuver', 3535]  # +++
                    if cm_0 and inf:
                        if (cm_0['get_off_remain_time'] > 0 or cm_0['on_board'] == 0) and \
                                inf['on_board'] == 0 and inf['get_on_remain_time'] <= 0:
                            self.task_copy[RedOprs.IFV] = ['load', RedOprs.Infantry]  # +++
                    if inf:
                        if inf['get_on_remain_time'] > 0:
                            self.task_copy[RedOprs.IFV] = ['deliver', RedOprs.Infantry, 3941]
                if inf:
                    if ifv['cur_hex'] == 3941 and inf['get_off_remain_time'] > 0:
                        self.task_copy[RedOprs.Infantry] = ['ambush3rd', 3740, False]
                        # 战车实施“火力支援任务”
                        self.task_copy[RedOprs.IFV] = ['support_firepower', get_range(3737, 3, map_size)]
            if cm_0:
                flag_targeted_kill = False
                if RedOprs.CM_0 in self.task_copy.keys():
                    if 'targeted_kill' in self.task_copy[RedOprs.CM_0]:
                        flag_targeted_kill = True
                if not flag_targeted_kill:
                    if cur_step <= 280:
                        if cm_0['cur_hex'] == 3535:
                            self.task_copy[RedOprs.CM_0] = ['maneuver', 3538]  # +++
                        if cm_0['cur_hex'] == 3538:
                            self.task_copy[RedOprs.CM_0] = ['maneuver', 3535]  # +++
                    else:
                        if cm_0['cur_hex'] in [3535, 3536, 3537, 3538]:
                            self.task_copy[RedOprs.CM_0] = ['maneuver', 4238]  # +++
                        if cm_0['cur_hex'] == 4238:
                            self.task_copy[RedOprs.CM_0] = ['cruise_missile']  # +++
        elif 'Control' in self.tactic:  # 主夺控点的夺控阶段
            flag_vehicle = False
            for enemy_info in myAgent.situations.enemies:
                enemy = enemy_info['operator']
                if enemy['type'] == BopType.Vehicle:
                    flag_vehicle = True
                    break
            if flag_vehicle:
                if tank:
                    self.task_copy[RedOprs.Tank] = ['fire_propulsion']  # +++
                if ifv:
                    if ifv['remain_bullet_nums'][BulletType.HeavyMissile] <= 0 or not ucv:
                        self.task_copy[RedOprs.IFV] = ['fire_propulsion']  # +++
                if ucv:
                    if ifv:
                        if ifv['remain_bullet_nums'][BulletType.HeavyMissile] <= 0:
                            self.task_copy[RedOprs.UCV] = ['fire_propulsion']  # +++
                    else:
                        self.task_copy[RedOprs.UCV] = ['fire_propulsion']  # +++
            else:
                use_oprs = []
                for opr in [tank, ifv, ucv, inf]:
                    if opr:
                        use_oprs.append(opr)
                # -- 确定夺控(反夺控)算子 --
                control_opr_main, control_opr_secondary = None, None
                cost_matrix = myAgent.my_map['cost_matrix'][0]
                if use_oprs:
                    min_dist = 1000
                    for opr in use_oprs:
                        if opr['type'] == BopType.Vehicle:
                            cur_dist = cost_matrix[
                                mapid_2_matind(main_city['coord'], map_size), mapid_2_matind(opr['cur_hex'], map_size)]
                        else:
                            cur_dist = cal_distance(main_city['coord'], opr['cur_hex']) * 144
                        if cur_dist < min_dist:
                            min_dist = cur_dist
                            control_opr_main = opr
                    use_oprs.remove(control_opr_main)  # 确定夺控算子
                if use_oprs:
                    min_dist = 1000
                    for opr in use_oprs:
                        if opr['type'] == BopType.Vehicle:
                            cur_dist = cost_matrix[
                                mapid_2_matind(secondary_city['coord'], map_size), mapid_2_matind(opr['cur_hex'], map_size)]
                        else:
                            cur_dist = cal_distance(secondary_city['coord'], opr['cur_hex']) * 144
                        if cur_dist < min_dist:
                            min_dist = cur_dist
                            control_opr_secondary = opr
                    use_oprs.remove(control_opr_secondary)  # 确定夺控算子
                # -- 分派夺控/反夺控任务 --
                if control_opr_main:
                    if main_city['flag'] != self.color:
                        self.task_copy[control_opr_main['obj_id']] = ['control', main_city['coord']]  # +++
                    else:
                        self.task_copy[control_opr_main['obj_id']] = ['defend_firepower', main_city['coord'], []]  # +++
                if control_opr_secondary:
                    if secondary_city['flag'] != self.color:
                        self.task_copy[control_opr_secondary['obj_id']] = ['control', secondary_city['coord']]  # +++
                    else:
                        self.task_copy[control_opr_secondary['obj_id']] = ['defend_firepower', secondary_city['coord'],
                                                                           []]  # +++
                # -- 为剩余算子分派火力输出任务 --
                remain_enemies = []
                for enemy_info in myAgent.situations.enemies:
                    if enemy_info['spread_flag']:
                        remain_enemies.append(enemy_info['operator'])
                if remain_enemies:
                    tar_area = []
                    for enemy in remain_enemies:
                        if cal_distance(enemy['cur_hex'], main_city['coord']) <= 3 or \
                                cal_distance(enemy['cur_hex'], secondary_city['coord']) <= 3:
                            tar_area.append(enemy['cur_hex'])
                    if tar_area:
                        for opr in use_oprs:
                            if opr['sub_type'] not in [BopType.IFV, BopType.UCV]:
                                self.task_copy[opr['obj_id']] = ['output_firepower', tar_area]  # +++
            # -- 夺控阶段cm的任务 --
            cm_0, cm_1 = myAgent.get_bop(RedOprs.CM_0), myAgent.get_bop(RedOprs.CM_1)
            cm = cm_0 if cm_0 else (cm_1 if cm_1 else None)
            if cm:
                cm_target = None
                for enemy_info in myAgent.situations.enemies:
                    if enemy_info['spread_flag']:
                        enemy = enemy_info['operator']
                        dist_main = cal_distance(enemy['cur_hex'], main_city['coord'])
                        dist_secondary = cal_distance(enemy['cur_hex'], secondary_city['coord'])
                        if enemy['type'] == BopType.Infantry and (dist_main <= 1 or dist_secondary <= 1):
                            cm_target = enemy['obj_id']
                            break
                if cm_target:
                    self.task_copy[cm['obj_id']] = ['targeted_kill', cm_target]

        '''=== 零星任务 ==='''
        # -- UCV的侦察任务 --
        if ucv:
            if cur_step > 400:
                # flag_hide = False
                # if blue_tank_0:
                #     if blue_tank_0['cur_hex'] >= 4000:
                #         flag_hide = True
                # if blue_tank_1:
                #     if blue_tank_1['cur_hex'] >= 4000:
                #         flag_hide = True
                # if not flag_hide:
                tar_area = [3636, 3638, 3738, 3739]
                self.task_copy[RedOprs.UCV] = ['scout', tar_area]  # +++
        # -- 发射第二枚巡飞弹 --
        if self.check_red_launch_2nd_cm(myAgent) and cur_step >= 550:
            if RedOprs.IFV in self.task_copy.keys():
                if 'unload' not in self.task_copy[RedOprs.IFV]:
                    self.task_backup[RedOprs.IFV] = self.task_copy.pop(RedOprs.IFV)  # 备份原任务
                    self.task_copy[RedOprs.IFV] = ['unload', RedOprs.CM_1, False]  # +++
                    self.task_copy[RedOprs.CM_1] = ['cruise_missile']
            else:
                self.task_copy[RedOprs.IFV] = ['unload', RedOprs.CM_1, False]  # +++
                self.task_copy[RedOprs.CM_1] = ['cruise_missile']
        if cm_1:
            if cm_1['on_board'] == 1 and cm_1['get_off_remain_time'] > 0 and RedOprs.IFV in self.task_backup.keys():
                self.task_copy[RedOprs.IFV] = self.task_backup.pop(RedOprs.IFV)
        # -- 巡飞弹的条件打击任务 --
        cm_0, cm_1 = myAgent.get_bop(RedOprs.CM_0), myAgent.get_bop(RedOprs.CM_1)
        cm = cm_0 if cm_0 else (cm_1 if cm_1 else None)
        if cm:
            flag_ifv_getoff, flag_inf_in_range = False, False
            cm_target = None
            enemy_ifv_0, enemy_ifv_1 = myAgent.get_enemy(BlueOprs.IFV_0), myAgent.get_enemy(BlueOprs.IFV_1)
            if enemy_ifv_0:
                if enemy_ifv_0['get_off_partner_id']:
                    flag_ifv_getoff = True
                    cm_target = BlueOprs.IFV_0
            if not flag_ifv_getoff:
                if enemy_ifv_1:
                    if enemy_ifv_1['get_off_partner_id']:
                        flag_ifv_getoff = True
                        cm_target = BlueOprs.IFV_1
            if not flag_ifv_getoff:
                for blue_inf_id in [BlueOprs.Infantry_0, BlueOprs.Infantry_1]:
                    blue_inf = myAgent.get_enemy(blue_inf_id)
                    if blue_inf:
                        if cal_distance(blue_inf['cur_hex'], secondary_city['coord']) <= 1:
                            flag_inf_in_range = True
                            cm_target = blue_inf_id
                            break
            if flag_ifv_getoff or flag_inf_in_range:
                self.task_copy[cm['obj_id']] = ['targeted_kill', cm_target]
        # == 主次夺控点的夺控 ==
        if main_city['flag'] != self.color:
            control_opr_main = None
            for opr in myAgent.get_our_oprs():
                if opr['type'] != BopType.Aircraft:
                    if cal_distance(opr['cur_hex'], main_city['coord']) <= 1:
                        control_opr_main = opr
            can_control = True
            for enemy_info in myAgent.situations.enemies:
                enemy = enemy_info['operator']
                if cal_distance(enemy['cur_hex'], main_city['coord']) <= 1 and enemy_info['spread_flag']:
                    can_control = False
            if can_control:
                if control_opr_main:
                    if control_opr_main['obj_id'] in self.task_copy.keys():
                        self.task_backup[control_opr_main['obj_id']] = self.task_copy.pop(control_opr_main['obj_id'])
                        self.task_copy[control_opr_main['obj_id']] = ['control', main_city['coord']]  # +++
                    else:
                        self.task_copy[control_opr_main['obj_id']] = ['control', main_city['coord']]  # +++
        if secondary_city['flag'] != self.color:
            control_opr_secondary = None
            for opr in myAgent.get_our_oprs():
                if opr['type'] != BopType.Aircraft:
                    if cal_distance(opr['cur_hex'], secondary_city['coord']) <= 1:
                        control_opr_secondary = opr
            can_control = True
            for enemy_info in myAgent.situations.enemies:
                enemy = enemy_info['operator']
                if cal_distance(enemy['cur_hex'], secondary_city['coord']) <= 1 and enemy_info['spread_flag']:
                    can_control = False
            if can_control:
                if control_opr_secondary:
                    if control_opr_secondary['obj_id'] in self.task_copy.keys():
                        self.task_backup[control_opr_secondary['obj_id']] = self.task_copy.pop(
                            control_opr_secondary['obj_id'])
                        self.task_copy[control_opr_secondary['obj_id']] = ['control',
                                                                           secondary_city['coord']]  # +++
                    else:
                        self.task_copy[control_opr_secondary['obj_id']] = ['control',
                                                                           secondary_city['coord']]  # +++
        # === 夺控后原任务恢复 ===
        for obj_id, task in self.task_copy.items():
            if 'control' in task:
                city_loc = task[1]
                obj = myAgent.get_bop(obj_id)
                if obj['cur_hex'] == city_loc:  # 完成夺控任务，恢复原任务
                    if obj_id in self.task_backup.keys():
                        self.task_copy[obj_id] = self.task_backup.pop(obj_id)
                    else:
                        self.task_copy[obj_id] = ['defend_firepower', city_loc, []]

    def develop_blue_strategies_ii(self, myAgent):
        map_size = myAgent.get_map_size()
        cur_step = myAgent.observation['time']['cur_step']
        tank_0, tank_1 = myAgent.get_bop(BlueOprs.Tank_0), myAgent.get_bop(BlueOprs.Tank_1)
        ifv_0, ifv_1 = myAgent.get_bop(BlueOprs.IFV_0), myAgent.get_bop(BlueOprs.IFV_1)
        inf_0, inf_1 = myAgent.get_bop(BlueOprs.Infantry_0), myAgent.get_bop(BlueOprs.Infantry_1)
        main_city, secondary_city = myAgent.get_city(3636), myAgent.get_city(3739)

        # === 确定self.tactic ===
        red_tank = myAgent.get_enemy(RedOprs.Tank)
        if not red_tank:
            self.tactic = ['Control']  # 夺控阶段
        elif self.max_step - cur_step <= 300:
            self.tactic = ['Control']  # 夺控阶段

        # === 任务分派 ===
        if 'Initiate' in self.tactic:  # 初始部署
            if tank_0:
                if tank_0['cur_hex'] == 3128:
                    self.task_copy[BlueOprs.Tank_0] = ['ambush', 3738]  # +++
            if tank_1:
                if tank_1['cur_hex'] == 3229:
                    self.task_copy[BlueOprs.Tank_1] = ['maneuver', 3739]  # +++
                elif tank_1['cur_hex'] == 3739:
                    self.task_copy[BlueOprs.Tank_1] = ['ambush', 3840]  # +++
            if ifv_0:
                if ifv_0['cur_hex'] == 3329:
                    if inf_0['on_board'] == 0 and inf_0['get_on_remain_time'] <= 0:
                        self.task_copy[BlueOprs.IFV_0] = ['load', BlueOprs.Infantry_0]  # +++
                    elif inf_0['get_on_remain_time'] > 0:
                        self.task_copy[BlueOprs.IFV_0] = ['deliver', BlueOprs.Infantry_0, 3735]  # +++
                elif ifv_0['cur_hex'] == 3735 and inf_0['get_off_remain_time'] > 0:
                    self.task_copy[BlueOprs.IFV_0] = ['ambush2nd', 3735, True]  # +++
                    self.task_copy[BlueOprs.Infantry_0] = ['ambush2nd', 3639, False]  # +++
            if ifv_1:
                if ifv_1['cur_hex'] == 3429:
                    if inf_1['on_board'] == 0 and inf_1['get_on_remain_time'] <= 0:
                        self.task_copy[BlueOprs.IFV_1] = ['load', BlueOprs.Infantry_1]  # +++
                    elif inf_1['get_on_remain_time'] > 0:
                        self.task_copy[BlueOprs.IFV_1] = ['deliver', BlueOprs.Infantry_1, 3534]  # +++
                elif ifv_1['cur_hex'] == 3534 and inf_1['get_off_remain_time'] > 0:
                    self.task_copy[BlueOprs.IFV_1] = ['ambush3rd', 3729, True]  # +++
                    self.task_copy[BlueOprs.Infantry_1] = ['maneuver', [3635, 3636, 3736, 3737]]  # +++ 顺路夺控
            if inf_1:
                if inf_1['cur_hex'] == 3737:
                    self.task_copy[BlueOprs.Infantry_1] = ['ambush2nd', 3737, False]  # +++
        if 'Control' in self.tactic:  # 夺控阶段
            if inf_1:
                if inf_1['cur_hex'] == 3737:
                    self.task_copy[BlueOprs.Infantry_1] = ['ambush2nd', 3737, False]  # +++
            if ifv_0:
                if tank_0:
                    self.task_copy[BlueOprs.IFV_0] = ['ambush2nd', 3735, False]  # +++
                else:
                    self.task_copy[BlueOprs.IFV_0] = ['ambush2nd', 3736, False]  # +++
            if inf_1:
                if not ifv_0 and not tank_0:
                    self.task_copy[BlueOprs.Infantry_1] = ['ambush2nd', 3736, False]  # +++
            if tank_0:
                self.task_copy[BlueOprs.Tank_0] = ['ambush2nd', 3736, False]  # +++
            if tank_1:
                self.task_copy[BlueOprs.Tank_1] = ['ambush2nd', 3839, False]  # +++

        ''' === 零星动作 === '''
        # == 主次夺控点的夺控 ==
        if cur_step > 500:
            cost_matrix = myAgent.my_map['cost_matrix'][0]
            if main_city['flag'] != self.color:
                control_opr_main = None
                min_dist = 1000
                for opr in myAgent.get_our_oprs():
                    if opr['obj_id'] == BlueOprs.Infantry_1 and cal_distance(opr['cur_hex'], main_city['coord']) <= 1:
                        control_opr_main = opr
                        break
                    else:
                        cur_dist = cost_matrix[
                            mapid_2_matind(main_city['coord'], map_size), mapid_2_matind(opr['cur_hex'], map_size)]
                        if cur_dist < min_dist:
                            min_dist = cur_dist
                            control_opr_main = opr
                can_control = True
                for enemy_info in myAgent.situations.enemies:
                    enemy = enemy_info['operator']
                    if cal_distance(enemy['cur_hex'], main_city['coord']) <= 1 and enemy_info['spread_flag']:
                        can_control = False
                if can_control:
                    if control_opr_main:
                        if control_opr_main['obj_id'] in self.task_copy.keys():
                            self.task_backup[control_opr_main['obj_id']] = self.task_copy.pop(control_opr_main['obj_id'])
                            self.task_copy[control_opr_main['obj_id']] = ['control', main_city['coord']]  # +++
                        else:
                            self.task_copy[control_opr_main['obj_id']] = ['control', main_city['coord']]  # +++
            if secondary_city['flag'] != self.color:
                control_opr_secondary = None
                min_dist = 1000
                for opr in myAgent.get_our_oprs():
                    if opr['obj_id'] == BlueOprs.Infantry_0 and cal_distance(opr['cur_hex'], secondary_city['coord']) <= 1:
                        control_opr_secondary = opr
                        break
                    else:
                        cur_dist = cost_matrix[
                            mapid_2_matind(secondary_city['coord'], map_size), mapid_2_matind(opr['cur_hex'], map_size)]
                        if cur_dist < min_dist:
                            min_dist = cur_dist
                            control_opr_secondary = opr
                can_control = True
                for enemy_info in myAgent.situations.enemies:
                    enemy = enemy_info['operator']
                    if cal_distance(enemy['cur_hex'], secondary_city['coord']) <= 1 and enemy_info['spread_flag']:
                        can_control = False
                if can_control:
                    if control_opr_secondary:
                        if control_opr_secondary['obj_id'] in self.task_copy.keys():
                            self.task_backup[control_opr_secondary['obj_id']] = self.task_copy.pop(control_opr_secondary['obj_id'])
                            self.task_copy[control_opr_secondary['obj_id']] = ['control',
                                                                               secondary_city['coord']]  # +++
                        else:
                            self.task_copy[control_opr_secondary['obj_id']] = ['control',
                                                                               secondary_city['coord']]  # +++
        # === 战车出击动作 ===
        if ifv_0:
            flag_move = False
            red_ifv_info, red_ucv_info = myAgent.get_enemy_info(RedOprs.IFV), myAgent.get_enemy_info(RedOprs.UCV)
            if red_ifv_info:
                if red_ifv_info['spread_flag']:
                    if cal_distance(red_ifv_info['operator']['cur_hex'], 3839) <= 2 and RedOprs.IFV not in ifv_0['see_enemy_bop_ids']:
                        flag_move = True
            if red_ucv_info:
                if red_ucv_info['spread_flag']:
                    if cal_distance(red_ucv_info['operator']['cur_hex'], 3839) <= 2 and RedOprs.UCV not in ifv_0['see_enemy_bop_ids']:
                        flag_move = True
            if flag_move:
                self.task_copy[BlueOprs.IFV_0] = ['ambush2nd', 3836, False]
        # === 夺控后原任务恢复 ===
        for obj_id, task in self.task_copy.items():
            if 'control' in task:
                city_loc = task[1]
                obj = myAgent.get_bop(obj_id)
                if obj['cur_hex'] == city_loc:  # 完成夺控任务，恢复原任务
                    if obj_id in self.task_backup.keys():
                        self.task_copy[obj_id] = self.task_backup.pop(obj_id)
                    else:
                        self.task_copy[obj_id] = ['defend_firepower', city_loc, []]

    def check_red_launch_2nd_cm(self, myAgent):
        """释放第二个巡飞弹的判断"""
        ifv, cm_0, cm_1 = myAgent.get_bop(RedOprs.IFV), myAgent.get_bop(RedOprs.CM_0), myAgent.get_bop(RedOprs.CM_1)
        if cm_0:
            return False
        if not ifv:
            return False
        if not cm_1:
            return False
        if cm_1['on_board'] == 0:
            return False
        if cm_1['get_off_remain_time'] > 0:
            return False
        return True

    def check_red_cm_shoot(self, myAgent):
        """判断巡飞弹是否射击主夺控点上的步兵"""
        cm_0, cm_1 = myAgent.get_bop(RedOprs.CM_0), myAgent.get_bop(RedOprs.CM_1)
        cm = cm_0 if cm_0 else (cm_1 if cm_1 else None)
        if not cm:
            return False
        if cm['on_board'] == 1:
            return False
        if cal_distance(cm['cur_hex'], 3636) > 20:
            return False
        for inf_id_ in [BlueOprs.Infantry_0, BlueOprs.Infantry_1]:
            inf_ = myAgent.get_enemy(inf_id_)
            if inf_:
                if inf_['cur_hex'] == 3636:
                    return True
        return False


def enemy_around_city(city_loc, myAgent):
    """
    判断夺控点及周边六角格是否有敌方单位
    """
    map_size = myAgent.get_map_size()
    area = get_range(city_loc, 1, map_size)
    enemies = myAgent.situations.enemies
    for enemy_info in enemies:
        if enemy_info['operator']['type'] != BopType.Aircraft and enemy_info['spread_flag']:
            enemy_loc = enemy_info['operator']['cur_hex']
            if enemy_loc in area:
                return True
    return False
